package netty.rpc.framework.core.netty.transport.client;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import netty.rpc.framework.core.netty.consumer.UncompletedRequest;
import netty.rpc.framework.core.netty.factory.SingletonFactory;
import netty.rpc.framework.core.netty.transport.protocol.RPCMessage;
import netty.rpc.framework.core.netty.transport.protocol.RPCRequest;
import netty.rpc.framework.core.netty.transport.protocol.RPCResponse;

/**
 * 客户端Netty接收RPCMessage消息后的处理类，
 * 将RPCMessage中的RPCResponse数据根据requestId 写入响应到CompletableFuture中去，
 * 为客户端获取RPC调用设置结果并删除ServiceHelper.completableFutureMap存储的CompletableFuture
 */
@Slf4j
public class ClientHandler extends ChannelInboundHandlerAdapter {

    private UncompletedRequest uncompletedRequest;

    public ClientHandler() {
        this.uncompletedRequest = SingletonFactory.getInstance(UncompletedRequest.class);
    }

    @Override
    public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {


        if( o instanceof RPCMessage){
            log.info("rpcResponse = {}",o.toString());

            RPCResponse rpcResponse = (RPCResponse) ((RPCMessage) o).getData();
            uncompletedRequest.completeFuture(rpcResponse.getRequestId(), rpcResponse);
            ReferenceCountUtil.release(o);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("channel is close");
    }
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (!(evt instanceof IdleStateEvent)) {
            return;
        }
        IdleStateEvent event = (IdleStateEvent) evt;
        String eventType = null;
        switch (event.state()) {
            case READER_IDLE:
                eventType = "读空闲";
                 // 读空闲的计数加1
                break;
            case WRITER_IDLE:
                eventType = "写空闲";
                // 不处理
                break;
            case ALL_IDLE:
                eventType = "读写空闲";
                // 不处理
                break;
        }

        if (ctx.channel().isActive()) {
            log.error("{} 超时事件：{}", ctx.channel().remoteAddress(), eventType);
        }
    }
}
